package org.hdl.anima.backend;

import org.hdl.anima.AppConf;
import org.hdl.anima.Application;
import org.hdl.anima.common.module.BasicModule;
import org.hdl.anima.session.LocalSession;
import org.hdl.anima.transport.Channel;
import org.hdl.anima.transport.RemoteException;
import org.hdl.anima.transport.Transporters;
import org.hdl.anima.transport.support.AbstractServer;
import org.hdl.anima.transport.support.ChannelHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author qiuhd
 * @since  2014年8月15日
 */
public class BackendServer extends BasicModule {

	private static final Logger logger = LoggerFactory.getLogger(BackendServer.class);
	private AbstractServer server ;
	private AppConf conf ;
	private Application application;
	
	private static final String HANDLER_KEY= "handler";
	
	public BackendServer(String moduleName) {
		super(moduleName);
	}
	
	private ChannelHandlerAdapter handler = new ChannelHandlerAdapter(){
		
		@Override
		public void connected(Channel channel) throws RemoteException {
			if (channel.getAttribute(HANDLER_KEY) == null) {
				BackendHandler handler = new BackendHandler(application,channel);
				channel.setAttribute(HANDLER_KEY, handler);
			}
		}
		
		@Override
		public void caught(Channel channel, Throwable cause) throws RemoteException {
			logger.error("caught exception:{}",cause.getMessage(),cause);
		}

		@Override
		public void disconnected(Channel channel) throws RemoteException {
			BackendHandler handler = (BackendHandler) channel.getAttribute(HANDLER_KEY);
			if (handler != null) {
				LocalSession session = handler.getLocalSession();
				session.close();
			}
		}

		@Override
		public void received(Channel channel, Object message)throws RemoteException {
			try {
				BackendHandler handler = (BackendHandler) channel.getAttribute(HANDLER_KEY);
				if (handler != null) {
					handler.process(message);
				}
			} catch (Exception e) {
				throw new RemoteException("Failed to handle message,cause : " + e.getMessage(),e);
			}
		}
	};

	@Override
	public void initialize(Application application) {
		super.initialize(application);
		this.conf = application.getAppConf();
		this.application = application;
	}

	@Override
	public void start() throws IllegalStateException {
		try {
			BackendCodec codec = new BackendCodec(application);
			Transporters.bind(conf, handler,codec);
		} catch (RemoteException e) {
			throw new IllegalStateException("Failed start backend server,cause :" + e.getMessage(),e);
		}
	}

	@Override
	public void stop() {
		if (server != null) {
			server.close();
		}
	}

	@Override
	public void destroy() {
		stop();
		if (server != null) {
			server = null;
		}
	}
}

